﻿using Artizan.Iot.Hub.Mqtt.Application;
using Microsoft.AspNetCore.Cors;
using Microsoft.OpenApi.Models;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;
using Volo.Abp.VirtualFileSystem;
using Artizan.Iot.Hub.Mqtt.AspNetCore;
using Artizan.Iot.Hub.Mqtt.Server;
using Autofac.Core;
using Artizan.Iot.Hub.Mqtt.AspNetCore.Servser;
using MQTTnet.AspNetCore;
using Artizan.Iot.Hub.Mqtt.AspNetCore.Extensions;

namespace Artizan.Iot.Hub.Mqtt.HttpApi.Host
{
    [DependsOn(
        typeof(AbpAutofacModule),
        typeof(AbpAspNetCoreSerilogModule),
        typeof(AbpSwashbuckleModule),
        typeof(ArtizanIotHubMqttApplicationModule),
        typeof(ArtizanIotHubMqttHttpApiModule),
        typeof(ArtizanIotHubMqttAspNetCoreModule)
    )]
    public class ArtizanIotHubMqttHttpApiHostModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var hostingEnvironment = context.Services.GetHostingEnvironment();
            var configuration = context.Services.GetConfiguration();

            //Configure<AbpDbContextOptions>(options =>
            //{
            //    options.UseSqlServer();
            //});

            //Configure<AbpMultiTenancyOptions>(options =>
            //{
            //    options.IsEnabled = MultiTenancyConsts.IsEnabled;
            //});

            Configure<AbpAspNetCoreMvcOptions>(options =>
            {
                //自动生成API Controllers
                options.ConventionalControllers.Create(typeof(ArtizanIotHubMqttApplicationModule).Assembly);
            });

            if (hostingEnvironment.IsDevelopment())
            {
                Configure<AbpVirtualFileSystemOptions>(options =>
                {
                    //options.FileSets.ReplaceEmbeddedByPhysical<ArtizanIotHubMqttDomainSharedModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}Artizan.Iot.Hub.Domain.Shared", Path.DirectorySeparatorChar)));
                    //options.FileSets.ReplaceEmbeddedByPhysical<ArtizanIotHubMqttDomainModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}Artizan.Iot.Hub.Domain", Path.DirectorySeparatorChar)));
                    options.FileSets.ReplaceEmbeddedByPhysical<ArtizanIotHubMqttApplicationContractsModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}Artizan.Iot.Hub.Mqtt.Application.Contracts", Path.DirectorySeparatorChar)));
                    options.FileSets.ReplaceEmbeddedByPhysical<ArtizanIotHubMqttApplicationModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}Artizan.Iot.Hub.Mqtt.Application", Path.DirectorySeparatorChar)));
                });
            }

            //context.Services.AddAbpSwaggerGenWithOAuth(
            //    configuration["AuthServer:Authority"],
            //    new Dictionary<string, string>
            //    {
            //        {"IotHub", "IotHub API"}
            //    },
            //    options =>
            //    {
            //        options.SwaggerDoc("v1", new OpenApiInfo {Title = "IotHub API", Version = "v1"});
            //        options.DocInclusionPredicate((docName, description) => true);
            //        options.CustomSchemaIds(type => type.FullName);
            //    });

            context.Services.AddAbpSwaggerGen(
                options =>
                {
                    options.SwaggerDoc("v1", new OpenApiInfo { Title = "IotHub API", Version = "v1" });
                    options.DocInclusionPredicate((docName, description) => true);
                    options.CustomSchemaIds(type => type.FullName);
                });

            Configure<AbpLocalizationOptions>(options =>
            {
                options.Languages.Add(new LanguageInfo("en", "en", "English"));
                options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
            });

            //context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            //    .AddJwtBearer(options =>
            //    {
            //        options.Authority = configuration["AuthServer:Authority"];
            //        options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]);
            //        options.Audience = "IotHub";
            //    });

            //Configure<AbpDistributedCacheOptions>(options =>
            //{
            //    options.KeyPrefix = "IotHub:";
            //});

            //var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("IotHub");
            //if (!hostingEnvironment.IsDevelopment())
            //{
            //    var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
            //    dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "IotHub-Protection-Keys");
            //}

            context.Services.AddCors(options =>
            {
                options.AddDefaultPolicy(builder =>
                {
                    builder
                        .WithOrigins(
                            configuration["App:CorsOrigins"]
                                .Split(",", StringSplitOptions.RemoveEmptyEntries)
                                .Select(o => o.RemovePostFix("/"))
                                .ToArray()
                        )
                        .WithAbpExposedHeaders()
                        .SetIsOriginAllowedToAllowWildcardSubdomains()
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                });
            });

            ConfigureIotHubMqttServer(context);
        }

        private void ConfigureIotHubMqttServer(ServiceConfigurationContext context)
        {
            context.Services.AddIotHubMqttServer(builder =>
            {
                builder.WithDefaultEndpoint();
            });
        }

        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseCorrelationId();
            app.UseStaticFiles();
            app.UseRouting();
            app.UseCors();
            app.UseAuthentication();
            //if (MultiTenancyConsts.IsEnabled)
            //{
            //    app.UseMultiTenancy();
            //}
            app.UseAbpRequestLocalization();
            app.UseAuthorization();
            app.UseSwagger();
            app.UseAbpSwaggerUI(options =>
            {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support APP API");

                //var configuration = context.GetConfiguration();
                //options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
                //options.OAuthScopes("IotHub");
            });

            app.UseIotHubMqttServer();
            app.UseAuditing();
            app.UseAbpSerilogEnrichers();
            app.UseConfiguredEndpoints();       
        }
    }
}
